package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.client.ItemClient;
import com.hmall.common.client.UserClient;
import com.hmall.common.dto.Address;
import com.hmall.common.dto.Item;
import com.hmall.order.interceptor.UserThreadLocal;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.pojo.OrderParam;
import com.hmall.order.service.IOrderService;
import com.hmall.order.service.OrderDetailService;
import com.hmall.order.service.OrderLogisticsService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Autowired
    ItemClient itemClient;

    @Autowired
    OrderDetailService detailService;

    @Autowired
    OrderLogisticsService logisticsService;

    @Autowired
    UserClient userClient;


    // 保存订单
    @GlobalTransactional  // XA 微服务全局事务
    //@Transactional
    @Override
    public Long saveOrder(OrderParam param) {
        //1. 根据雪花算法生成订单id    订单id上加 生成雪花算法的注解@TableId(type = IdType.ASSIGN_ID)
        //2. 商品微服务提供 FeignClient, 实现根据id查询商品接口
        //3. 根据itemId 查询商品信息
        Item item = itemClient.getItemById(param.getItemId());
        //4. 基于商品价格, 购买数量计算商品总价: totalFee
        Long totalFee = item.getPrice() * param.getNum();
        //5. 封装Order对象, 初始 status 为未支付
        Order order = new Order();
        order.setTotalFee(totalFee);
        order.setStatus(1);
        order.setPaymentType(param.getPaymentType());
        // 从本地线程中获取用户信息
        Long userId = UserThreadLocal.get();
        order.setUserId(userId);
        order.setCreateTime(new Date());
        //6. 将 Order 写入数据库 tb_order表中
        this.save(order);
        //7. 将商品信息, orderId 信息封装为OrderDetail 对象, 写入 tb_detail表
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(order.getId());
        orderDetail.setItemId(item.getId());
        orderDetail.setNum(param.getNum());
        orderDetail.setName(item.getName());
        orderDetail.setSpec(item.getSpec());
        orderDetail.setPrice(item.getPrice());
        orderDetail.setImage(item.getImage());
        orderDetail.setCreateTime(new Date());
        orderDetail.setUpdateTime(new Date());
        detailService.save(orderDetail);
        //8. 将user-service 的根据id 查询地址接口封装为 FeignClient
        //9. 根据addressId 查询user-service 服务, 获取地址信息
        Address address = userClient.findAddressById(param.getAddressId());
        //10. 将地址封装为  OrderLogistics 对象, 写入 tb_order_logistics表
        OrderLogistics logistics = new OrderLogistics();
        logistics.setOrderId(order.getId());
        logistics.setContact(address.getContact());
        logistics.setMobile(address.getMobile());
        logistics.setProvince(address.getProvince());
        logistics.setCity(address.getCity());
        logistics.setTown(address.getTown());
        logistics.setStreet(address.getStreet());
        logisticsService.save(logistics);
        //11. 在 item-service 提供减库存接口, 并编写FeignClient
        //12. 调用item-service 的减库存接口
        itemClient.reduceStock(item.getId(), param.getNum());
        // 模拟异常
        //int i = 1 / 0;
        return order.getId();
    }
}
